﻿using System;
using System.Collections.Generic;
using System.Reflection;

namespace Wizard.Data
{
    internal class FieldSerializer
    {
        private static Dictionary<Type, FieldSerializer> mSerializers = new Dictionary<Type, FieldSerializer>();
        private ConstructorInfo mConstructorInfo;
        private List<FieldInfo> mFields;
        private Type mType;

        private FieldSerializer(Type t)
        {
            mType = t;
            mConstructorInfo = mType.GetConstructor(new Type[] {});
            mFields = new List<FieldInfo>();

            if (mConstructorInfo==null)
                    throw new Exception(
                        string.Format("Cannot create Serializer for {0}. There is no parameterless constructor.",
                            mType.Name));
            foreach (FieldInfo fi in t.GetFields(
                BindingFlags.Instance
                | BindingFlags.Public
                | BindingFlags.NonPublic))
            {
                if (fi.Name != "mDataStoreId") mFields.Add(fi);
            }
        }

        public static FieldSerializer Get(CacheableObject o)
        {
            FieldSerializer result = null;
            if (!mSerializers.TryGetValue(o.GetType(), out result))
            {
                result = new FieldSerializer(o.GetType());
            }
            return result;
        }

        internal void LoadFromDataStore(IRecordReader reader, CacheableObject o)
        {
            foreach (var fi in mFields)
            {
                var value = reader.Read(fi.Name, fi.FieldType);
                fi.SetValue(o, value);
            }
        }

        internal void SaveToDataStore(IRecordWriter writer, CacheableObject o)
        {
            foreach (var fi in mFields)
            {
                var value = fi.GetValue(o);
                writer.Write(fi.Name, fi.FieldType, value);
            }
        }
    }
}
